package com.hk.springsecurity04.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import java.io.Serializable;
import java.util.*;

/**
 * @author by 何坤
 * @Classname UserEntity
 * @Description TODO
 * @Date 2019/11/28 14:46
 */
@Entity
@Table(name = "tab_user")
public class UserEntity implements UserDetails, Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "u_id", length = 11, nullable = false)
    private Integer id;

    @Column(name = "u_email", length = 20, nullable = true)
    private String email;

    @Column(name = "u_phone", length = 11, nullable = false)
    private String phone;

    @Column(name = "u_nickname", length = 10, nullable = false)
    private String nickname;

    @Column(name = "u_password", length = 255, nullable = false)
    private String password;

    @Column(name = "u_birthday", nullable = true)
    private Date birthday;

    @Column(name = "u_locked", nullable = false)
    private Boolean locked;

    @Column(name = "u_enabled", nullable = false)
    private Boolean enabled;

    @ManyToMany(targetEntity = RoleEntity.class, fetch = FetchType.EAGER)
    @JoinTable(name = "tab_user_role",
            joinColumns = {@JoinColumn(name = "ur_uphone", referencedColumnName = "u_phone")},
            inverseJoinColumns = {@JoinColumn(name = "ur_rid", referencedColumnName = "role_id")})
    private Set<RoleEntity> roles;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Set<RoleEntity> getRoles() {
        return roles;
    }

    public void setRoles(Set<RoleEntity> roles) {
        this.roles = roles;
    }

    public Boolean getLocked() {
        return locked;
    }

    public void setLocked(Boolean locked) {
        this.locked = locked;
    }

    public Boolean getEnabled() {
        return enabled;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (RoleEntity roleEntity : roles) {
            authorities.add(new SimpleGrantedAuthority(roleEntity.getRoleEn()));
        }
        return authorities;
    }

    @Override
    public String getUsername() {
        return nickname;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }


    /**
     * Spring Security为了实现会话并发控制，采用了会话信息表来管理用户的会话状态。具体实现见SessionRegistryImpl类。
     * 其中的principals是ConcurrentMap，其中principals采用用户的信息作为key，所以必须重写equals和hashcode方法。
     * @param obj
     * @return boolean
     * @date 2019/11/29 21:33
     * @author 何坤
     */
    @Override
    public boolean equals(Object obj) {
        return obj instanceof UserEntity ? ((UserEntity) obj).getPhone().equals(this.phone) : false;
    }

    @Override
    public int hashCode() {
        return this.phone.hashCode();
    }

    @Override
    public String toString() {
        return "UserEntity{" +
                "id=" + id +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", nickname='" + nickname + '\'' +
                ", password='" + password + '\'' +
                ", birthday=" + birthday +
                ", locked=" + locked +
                ", enabled=" + enabled +
                ", roles=" + roles +
                '}';
    }
}
